﻿using System;
using System.Management;
using ClusterAwareProperties.Properties;

namespace ClusterAwareProperties
{
    /// <summary>
    /// Wrapper class Cluster ManagementObject
    /// </summary>
    public class ClusterProperties : IDisposable
    {
        #region private property

        private readonly ManagementObject _classInstance;

        #endregion

        #region ctor

        /// <summary>
        /// constuctor
        /// </summary>
        private ClusterProperties()
        {
            Status = StatusResource.Unknown;
            QuorumType = QuorumTypeEnum.Unknown;
            FixQuorum = FixQuorumState.Unknown;
            EnableSharedVolumes = SharedVolumes.Unknown;
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="queryobj">Cluster ManagementObject instance</param>
        public ClusterProperties(ManagementObject queryobj)
            : this()
        {
            var path = queryobj.ToString();
            if (path.IndexOf("\\root\\MSCluster:MSCluster_Cluster") == -1)
            {
                throw new ClusterManagerException(string.Format(Resources.Error_TypeClassInvalid, path, "\\root\\MSCluster:MSCluster_Cluster"));
            }
            _classInstance = queryobj;
            this.Convert(queryobj);
        }

        #endregion

        #region public properties

        /// <summary>
        /// Return instance of Resource ManagementObject
        /// </summary>
        public ManagementObject Instance
        {
            get { return _classInstance; }
        }

        /// <summary>
        /// Provides a short textual description of the cluster.
        /// </summary>
        public string Caption { get; internal set; }

        /// <summary>
        /// Indicates when the cluster was installed. 
        /// A lack of a value does not indicate that the cluster is not installed.
        /// </summary>
        public DateTime? InstallDate { get; internal set; }

        /// <summary>
        /// Indicates the current status of the cluster.
        /// </summary>
        public StatusResource Status { get; internal set; }

        /// <summary>
        /// Indicates the name of the class or the subclass used in the creation of an instance. 
        /// When used with the other key properties of this class, this property allows all instances of this class and its subclasses to be uniquely identified.
        /// </summary>
        public string CreationClassName { get; internal set; }

        /// <summary>
        /// Provides information on how the primary system owner can be reached.
        /// </summary>
        public string PrimaryOwnerContact { get; internal set; }

        /// <summary>
        /// The name of the primary system owner.
        /// </summary>
        public string PrimaryOwnerName { get; internal set; }

        /// <summary>
        /// Specifies the roles the cluster plays in the IT environment.
        /// </summary>
        public string[] Roles { get; internal set; }

        /// <summary>
        /// Identifies the manner in which the system name was created.
        /// </summary>
        public string NameFormat { get; internal set; }

        /// <summary>
        /// Captures additional data, beyond system name information, that can be used to identify a cluster.
        /// </summary>
        public string[] OtherIdentifyingInfo { get; internal set; }

        /// <summary>
        /// Provides explanations and details of the entries in the OtherIdentifyingInfo property array. 
        /// Each entry of this array is related to the entry in the OtherIdentifyingInfo property that is located at the same index.
        /// </summary>
        public string[] IdentifyingDescriptions { get; internal set; }

        /// <summary>
        /// Indicates whether the cluster is a special-purpose cluster.
        /// </summary>
        public UInt16[] Dedicated { get; internal set; }

        /// <summary>
        /// Indicates the maximum number of nodes that can participate in a cluster. 
        /// A value of zero indicates that an unlimited number of nodes can participate in the cluster.
        /// </summary>
        public UInt32 MaxNumberOfNodes { get; internal set; }

        /// <summary>
        /// Specifies the name of the cluster.
        /// </summary>
        public string Name { get; internal set; }

        /// <summary>
        /// Provides access to the cluster's Description property.
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Indicates the location of a maintenance file.
        /// </summary>
        public string MaintenanceFile { get; set; }

        /// <summary>
        /// Provides the class identifiers (CLSIDs) for the Cluster Administrator extension DLLs associated with the cluster.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] AdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for groups.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] GroupAdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for nodes.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] NodeAdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for resources.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] ResourceAdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for resource types.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] ResourceTypeAdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for networks.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] NetworkAdminExtensions { get; set; }

        /// <summary>
        /// Provides access to the AdminExtensions property for network interfaces.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] NetworkInterfaceAdminExtensions { get; set; }

        /// <summary>
        /// Sets or retrieves the size of the quorum log file.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public UInt32? QuorumLogFileSize { get; set; }

        /// <summary>
        /// Gets the current quorum type.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public QuorumTypeEnum QuorumType { get; internal set; }

        /// <summary>
        /// Maintains quorum files.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public string QuorumPath { get; internal set; }

        /// <summary>
        /// Lists networks in priority order. The first in the array has the highest priority.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public string[] NetworkPriorities { get; set; }

        /// <summary>
        /// Provides access to the cluster's DefaultNetworkRole property.
        /// </summary>
        public UInt32 DefaultNetworkRole { get; set; }

        /// <summary>
        /// Controls whether a node's system, application, and security event log entries are replicated in the event logs of all other cluster nodes.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public UInt32? EnableEventLogReplication { get; set; }

        /// <summary>
        /// Provides access to the cluster's Security Descriptor property.
        /// </summary>
        public UInt16[] SecurityDescriptor { get; internal set; }

        /// <summary>
        /// Controls the maximum time necessary to decide the Quorum owner node.
        /// </summary>
        public UInt32 QuorumArbitrationTimeMax { get; set; }

        /// <summary>
        /// Controls the minimum time necessary to decide the Quorum owner node.
        /// </summary>
        public UInt32 QuorumArbitrationTimeMin { get; set; }

        /// <summary>
        /// Specifies the overall time period (in seconds) used to determine if a resource access deadlock condition has occurred. See ResourceDllDeadlockPeriod.
        /// </summary>
        /// <remarks>
        /// This property is not supported in Windows2008
        /// </remarks>
        public UInt32? ResourceDllDeadlockPeriod { get; internal set; }

        /// <summary>
        /// Controls how long a node will wait on other nodes in a membership stage before deciding that they failed.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusSvcHangTimeout { get; internal set; }

        /// <summary>
        /// Controls how long a node will wait on other nodes in the opening stage before deciding that they failed.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusSvcRegroupOpeningTimeout { get; internal set; }

        /// <summary>
        /// Plumbs all possible cross subnet routes to all nodes.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? PlumbAllCrossSubnetRoutes { get; set; }

        /// <summary>
        /// Controls how long a node will wait on other nodes in a membership stage before deciding that they failed.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusSvcRegroupStageTimeout { get; internal set; }

        /// <summary>
        /// Controls how long the membership leader will wait to reach full connectivity between cluster nodes.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusSvcRegroupPruningTimeout { get; internal set; }

        /// <summary>
        /// Controls how frequently the membership algorithm is sending periodic membership messages.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusSvcRegroupTickInMilliseconds { get; internal set; }

        /// <summary>
        /// Controls the maximum size of the cluster log files on each of the nodes.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusterLogSize { get; set; }

        /// <summary>
        /// Controls the level of cluster logging.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? ClusterLogLevel { get; set; }

        /// <summary>
        /// Controls the logging of resource controls.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? LogResourceControls { get; set; }

        /// <summary>
        /// Controls the action to take if the user-mode processes have stopped responding.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? HangRecoveryAction { get; set; }

        /// <summary>
        /// Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? SameSubnetDelay { get; set; }

        /// <summary>
        /// Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across subnets.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? CrossSubnetDelay { get; set; }

        /// <summary>
        /// Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? SameSubnetThreshold { get; set; }

        /// <summary>
        /// Controls how many Cluster Service heartbeats can be missed across subnets before it determines that Cluster Service has stopped responding.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? CrossSubnetThreshold { get; set; }

        /// <summary>
        /// Indicates whether a backup is in progress.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? BackupInProgress { get; set; }

        /// <summary>
        /// Controls the request reply time-out period.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? RequestReplyTimeout { get; set; }

        /// <summary>
        /// Controls private properties of the cluster.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public PrivatePropertiesData PrivateProperties { get; set; }

        /// <summary>
        /// Controls the witness restart interval.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? WitnessRestartInterval { get; set; }

        /// <summary>
        /// Controls the level of security that should apply to intracluster messages.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public LevelSecurity SecurityLevel { get; internal set; }

        /// <summary>
        /// Controls the maximum time in seconds that a cluster database write to a witness can take before the write is abandoned.
        /// </summary>
        /// <remarks>
        /// Windows Server 2003:  
        /// This property is not supported before Windows Server 2008.
        /// </remarks>
        public UInt32? WitnessDatabaseWriteTimeout { get; set; }

        /// <summary>
        /// Provides access to the cluster's AddEvictDelay property, which is the number a seconds that a new node is delayed after an eviction of another node.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public UInt32? AddEvictDelay { get; set; }

        /// <summary>
        /// Provides access to the cluster's FixQuorum property, which specifies if the cluster is in a fix quorum state.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public FixQuorumState FixQuorum { get; internal set; }

        /// <summary>
        /// Provides access to the cluster's IgnorePersistentStateOnStartup property, which specifies whether the cluster will bring online groups that were online when the cluster was shut down.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public IgnorePersistentState IgnorePersistentStateOnStartup { get; internal set; }

        /// <summary>
        /// Root directory from which the cluster shared volumes are linked.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public string SharedVolumesRoot { get; internal set; }

        /// <summary>
        /// Enables or disables cluster shared volumes on this cluster.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public SharedVolumes EnableSharedVolumes { get; set; }

        /// <summary>
        /// Certain classes of filter drivers may be flagged as incompatible with the direct I/O mode of shared volumes. 
        /// This property is used to override cluster service determination of filters as incompatible. 
        /// Compatible filter driver names are specified without the .sys extension.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public string[] SharedVolumeCompatibleFilters { get; set; }

        /// <summary>
        /// Certain classes of filter drivers may be incompatible with the direct I/O mode of shared volumes. 
        /// This property is used to add filters to be deemed as incompatible for direct I/O. 
        /// Incompatible filter driver names are specified without the .sys extension.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public string[] SharedVolumeIncompatibleFilters { get; set; }

        /// <summary>
        /// Maximum time in seconds that a group waits for its preferred node to come online during cluster startup before coming online on a different node.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public UInt32? ClusterGroupWaitDelay { get; set; }

        /// <summary>
        /// Provides access to the cluster's ShutdownTimeoutInMinutes property, which is the maximum time in minutes allowed for cluster resources to come offline during cluster service shutdown.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public UInt32? ShutdownTimeoutInMinutes { get; set; }

        /// <summary>
        /// Controls the amount of memory reserved for the parent partition on all cluster nodes.
        /// </summary>
        /// <remarks>
        /// Windows Server 2008 and Windows Server 2003:  
        /// This property is not supported before Windows Server 2008 R2.
        /// </remarks>
        public UInt32? RootMemoryReserved { get; set; }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Dispose Class
        /// </summary>
        public void Dispose()
        {
            if (Instance != null)
            {
                Instance.Dispose();
            }
        }

        #endregion
    }
}
